package eop.graham

import java.util.Map;
import grails.validation.ValidationException;


import grails.test.*

class DataServiceTests extends GrailsUnitTestCase {
	protected void setUp() {
		super.setUp()
	}

	protected void tearDown() {
		super.tearDown()
	}

	void testCheckEnoughFields() {

		List longList = [
			1,
			2,
			3,
			4,
			5,
			6,
			7,
			8,
			9,
			10,
			11,
			12,
			13,
			14,
			15,
			16,
			17,
			18,
			19,
			20,
			21,
			22,
			23,
			24,
			25,
			26,
			27,
			28,
			29,
			30,
			31,
			32,
			33,
			34,
			35,
			36,
			37,
			38,
			39,
			40,
			41,
			42,
			43,
			44,
			45,
			46,
			47,
			48,
		]

		List shortList = [
			1,
			2,
			3,
			4,
			5,
			6,
			7,
			8,
			9,
			10,
			11,
			12,
			13,
			14,
			15,
			16,
			17,
			18,
			19,
			20,
			21,
			22,
			23,
			24,
			25,
			26,
			27,
			28,
			29,
			30,
			31,
			32,
			33,
			34,
			35,
		]

		List correctList = [
			1,
			2,
			3,
			4,
			5,
			6,
			7,
			8,
			9,
			10,
			11,
			12,
			13,
			14,
			15,
			16,
			17,
			18,
			19,
			20,
			21,
			22,
			23,
			24,
			25,
			26,
			27,
			28,
			29,
			30,
			31,
			32,
			33,
			34,
			35,
			36,
			37,
			38,
			39,
			40,
			41,
			42,
			43,
			44,
			45,
		]

		DataService x = new DataService()

		//assert longList.class == List
		x.checkEnoughFields(longList)
		x.checkEnoughFields(shortList)
		x.checkEnoughFields(correctList)
	}

	void testMakeWellFormed() {

		// check that multiple vertical tabs (\v or \013) are detected
		// and no confusion with "\v" two-character sequence

		def badData = [
			'abcd',
			'ij\013kl',
			'a\013b\013\013\013\\vcd',
			'a\013b\013\\v\\ncd',
		]

		def goodData = [
			'abcd',
			'ij kl',
			'a b   \\vcd',
			'a b \\v\\ncd',
		]
		
		def wellFormedData = []

		DataService x = new DataService()
		wellFormedData = x.makeWellFormed(badData)
		assertEquals(wellFormedData,goodData)
	}

	void testRawDataToMap(){

		def testData = [
			"Chrna3",
			"Chrna3,(a)3,Acra3,Acra-3,A730007P14Rik",
			"cholinergic receptor, nicotinic, alpha polypeptide 3",
			"expressed in cx; no clear gradient",
			"08/01/2007",
			"denis",
			null,
			null,
			null,
			null,
			null,
			null,
			null,
			null,
			"Chrna3",
			"Chrna3",
			"Chrna3",
			null,
			0.9393345579,
			1.3002392637,
			1.1465281309,
			1.1340666039,
			0.4799785609,
			1.2445135169,
			0.385675651,
			1.4011137492,
			1.3032766718,
			"Chrna3",
			"0006810 // transport // inferred from electronic annotation /// 0006811 // ion transport // inferred from electronic annotation /// 0006937 // regulation of muscle contraction // inferred from mutant phenotype /// 0006940 // regulation of smooth muscle contraction // inferred from mutant phenotype /// 0007165 // signal transduction // inferred from electronic annotation /// 0007171 // activation of transmembrane receptor protein tyrosine kinase activity // inferred from mutant phenotype /// 0007271 // synaptic transmission, cholinergic // inferred from mutant phenotype /// 0007399 // nervous system development // inferred from electronic annotation /// 0007507 // heart development // inferred from electronic annotation /// 0007626 // locomotory behavior // inferred from mutant phenotype /// 0010035 // response to inorganic substance // inferred from electronic annotation /// 0014056 // regulation of acetylcholine secretion // inferred from mutant phenotype /// 0035095 // behavioral response to nicotine // inferred from mutant phenotype /// 0035095 // behavioral response to nicotine // inferred from electronic annotation /// 0042391 // regulation of membrane potential // inferred from mutant phenotype /// 0042493 // response to drug // not recorded /// 0042493 // response to drug // inferred from electronic annotation /// 0048814 // regulation of dendrite morphogenesis // inferred from mutant phenotype /// 0060079 // regulation of excitatory postsynaptic membrane potential // inferred from mutant phenotype /// 0060084 // synaptic transmission involved in micturition // inferred from mutant phenotype /// 0060084 // synaptic transmission involved in micturition // inferred from electronic annotation",
			"0005886 // plasma membrane // inferred from electronic annotation /// 0005892 // nicotinic acetylcholine-gated receptor-channel complex // inferred from physical interaction /// 0005892 // nicotinic acetylcholine-gated receptor-channel complex // inferred from electronic annotation /// 0014069 // postsynaptic density // not recorded /// 0014069 // postsynaptic density // inferred from electronic annotation /// 0016020 // membrane // inferred from electronic annotation /// 0016021 // integral to membrane // inferred from electronic annotation /// 0030054 // cell junction // inferred from electronic annotation /// 0030425 // dendrite // not recorded /// 0030425 // dendrite // inferred from electronic annotation /// 0043025 // neuronal cell body // not recorded /// 0043025 // neuronal cell body // inferred from electronic annotation /// 0045202 // synapse // inferred from electronic annotation /// 0045211 // postsynaptic membrane // inferred by curator /// 0045211 // postsynaptic membrane // inferred from electronic annotation",
			"0004872 // receptor activity // inferred from electronic annotation /// 0004889 // nicotinic acetylcholine-activated cation-selective channel activity // inferred from mutant phenotype /// 0004889 // nicotinic acetylcholine-activated cation-selective channel activity // not recorded /// 0004889 // nicotinic acetylcholine-activated cation-selective channel activity // inferred from electronic annotation /// 0005216 // ion channel activity // inferred from electronic annotation /// 0005230 // extracellular ligand-gated ion channel activity // inferred from electronic annotation /// 0015464 // acetylcholine receptor activity // not recorded /// 0015464 // acetylcholine receptor activity // inferred from electronic annotation /// 0042166 // acetylcholine binding // not recorded",
			43.7435,
			31.5705,
			1.386962552,
			0.721,
			0.012,
			0.777,
			0.461,
			0.819,
			0.339,
			0.899,
			0.312,
			0.845,
			0.84,
			0.132,
		]

		def resultMap = [:]

		DataService x = new DataService()
		resultMap = x.rawDataToMap(testData)
		assert resultMap.size() == DataService.COLUMN_NAME.size()
	}

	void testAddToDatabase() {

		Map testData = [
					(DataService.COLUMN_NAME[1]):"Chrna3",
					(DataService.COLUMN_NAME[2]):"Chrna3,(a)3,Acra3,Acra-3,A730007P14Rik",
					(DataService.COLUMN_NAME[3]):"cholinergic receptor, nicotinic, alpha polypeptide 3",
					(DataService.COLUMN_NAME[4]):"expressed in cx; no clear gradient",
					(DataService.COLUMN_NAME[5]):"08/01/2007",
					(DataService.COLUMN_NAME[6]):"denis",
					(DataService.COLUMN_NAME[7]):null,
					(DataService.COLUMN_NAME[8]):null,
					(DataService.COLUMN_NAME[9]):null,
					(DataService.COLUMN_NAME[10]):null,
					(DataService.COLUMN_NAME[11]):null,
					(DataService.COLUMN_NAME[12]):null,
					(DataService.COLUMN_NAME[13]):null,
					(DataService.COLUMN_NAME[14]):null,
					(DataService.COLUMN_NAME[15]):"Chrna3",
					(DataService.COLUMN_NAME[16]):"Chrna3",
					(DataService.COLUMN_NAME[17]):"Chrna3",
					(DataService.COLUMN_NAME[18]):null,
					(DataService.COLUMN_NAME[19]):0.9393345579,
					(DataService.COLUMN_NAME[20]):1.3002392637,
					(DataService.COLUMN_NAME[21]):1.1465281309,
					(DataService.COLUMN_NAME[22]):1.1340666039,
					(DataService.COLUMN_NAME[23]):0.4799785609,
					(DataService.COLUMN_NAME[24]):1.2445135169,
					(DataService.COLUMN_NAME[25]):0.385675651,
					(DataService.COLUMN_NAME[26]):1.4011137492,
					(DataService.COLUMN_NAME[27]):1.3032766718,
					(DataService.COLUMN_NAME[28]):"Chrna3",
					(DataService.COLUMN_NAME[29]):"0006810 // transport // inferred from electronic annotation /// 0006811 // ion transport // inferred from electronic annotation /// 0006937 // regulation of muscle contraction // inferred from mutant phenotype /// 0006940 // regulation of smooth muscle contraction // inferred from mutant phenotype /// 0007165 // signal transduction // inferred from electronic annotation /// 0007171 // activation of transmembrane receptor protein tyrosine kinase activity // inferred from mutant phenotype /// 0007271 // synaptic transmission, cholinergic // inferred from mutant phenotype /// 0007399 // nervous system development // inferred from electronic annotation /// 0007507 // heart development // inferred from electronic annotation /// 0007626 // locomotory behavior // inferred from mutant phenotype /// 0010035 // response to inorganic substance // inferred from electronic annotation /// 0014056 // regulation of acetylcholine secretion // inferred from mutant phenotype /// 0035095 // behavioral response to nicotine // inferred from mutant phenotype /// 0035095 // behavioral response to nicotine // inferred from electronic annotation /// 0042391 // regulation of membrane potential // inferred from mutant phenotype /// 0042493 // response to drug // not recorded /// 0042493 // response to drug // inferred from electronic annotation /// 0048814 // regulation of dendrite morphogenesis // inferred from mutant phenotype /// 0060079 // regulation of excitatory postsynaptic membrane potential // inferred from mutant phenotype /// 0060084 // synaptic transmission involved in micturition // inferred from mutant phenotype /// 0060084 // synaptic transmission involved in micturition // inferred from electronic annotation",
					(DataService.COLUMN_NAME[30]):"0005886 // plasma membrane // inferred from electronic annotation /// 0005892 // nicotinic acetylcholine-gated receptor-channel complex // inferred from physical interaction /// 0005892 // nicotinic acetylcholine-gated receptor-channel complex // inferred from electronic annotation /// 0014069 // postsynaptic density // not recorded /// 0014069 // postsynaptic density // inferred from electronic annotation /// 0016020 // membrane // inferred from electronic annotation /// 0016021 // integral to membrane // inferred from electronic annotation /// 0030054 // cell junction // inferred from electronic annotation /// 0030425 // dendrite // not recorded /// 0030425 // dendrite // inferred from electronic annotation /// 0043025 // neuronal cell body // not recorded /// 0043025 // neuronal cell body // inferred from electronic annotation /// 0045202 // synapse // inferred from electronic annotation /// 0045211 // postsynaptic membrane // inferred by curator /// 0045211 // postsynaptic membrane // inferred from electronic annotation",
					(DataService.COLUMN_NAME[31]):"0004872 // receptor activity // inferred from electronic annotation /// 0004889 // nicotinic acetylcholine-activated cation-selective channel activity // inferred from mutant phenotype /// 0004889 // nicotinic acetylcholine-activated cation-selective channel activity // not recorded /// 0004889 // nicotinic acetylcholine-activated cation-selective channel activity // inferred from electronic annotation /// 0005216 // ion channel activity // inferred from electronic annotation /// 0005230 // extracellular ligand-gated ion channel activity // inferred from electronic annotation /// 0015464 // acetylcholine receptor activity // not recorded /// 0015464 // acetylcholine receptor activity // inferred from electronic annotation /// 0042166 // acetylcholine binding // not recorded",
					(DataService.COLUMN_NAME[32]):43.7435,
					(DataService.COLUMN_NAME[33]):31.5705,
					(DataService.COLUMN_NAME[34]):1.386962552,
					(DataService.COLUMN_NAME[35]):0.721,
					(DataService.COLUMN_NAME[36]):0.012,
					(DataService.COLUMN_NAME[37]):0.777,
					(DataService.COLUMN_NAME[38]):0.461,
					(DataService.COLUMN_NAME[39]):0.819,
					(DataService.COLUMN_NAME[40]):0.339,
					(DataService.COLUMN_NAME[41]):0.899,
					(DataService.COLUMN_NAME[42]):0.312,
					(DataService.COLUMN_NAME[43]):0.845,
					(DataService.COLUMN_NAME[44]):0.84,
					(DataService.COLUMN_NAME[45]):0.132,
				]

		DataService x = new DataService()
		//	def y = x.addToDatabase(testData)

	}

	void testConstructorOK() {

		mockDomain(Data)
		Data d = new Data (
				geneName:"Chrna3",
				statMethod:"MAS5",
				POmIntensity:43.7435,
				POmFoldChangeP3:1.1465281309,
				POmFoldChangeP10:1.3002392637,
				VPIntensity:31.5705,
				VPFoldChangeP3:1.3032766718,
				VPFoldChangeP10:1.4011137492,
				probe:null,
				)
		d.validate()
		assertFalse d.hasErrors()
	}

	void testNullGeneNameFails() {

		mockDomain(Data)
		Data d = new Data (
				geneName:null,
				statMethod:"MAS5",
				POmIntensity:43.7435,
				POmFoldChangeP3:1.1465281309,
				POmFoldChangeP10:1.3002392637,
				VPIntensity:31.5705,
				VPFoldChangeP3:1.3032766718,
				VPFoldChangeP10:1.4011137492,
				probe:null,
				)
		assertFalse d.validate()
		assertTrue d.hasErrors()
		assert d.errors.getFieldError('geneName').code == 'nullable'
	}

	void testBlankGeneNameFails() {

		mockDomain(Data)
		Data d = new Data (
				geneName:"",
				statMethod:"MAS5",
				POmIntensity:43.7435,
				POmFoldChangeP3:1.1465281309,
				POmFoldChangeP10:1.3002392637,
				VPIntensity:31.5705,
				VPFoldChangeP3:1.3032766718,
				VPFoldChangeP10:1.4011137492,
				probe:null,
				)
		assertFalse d.validate()
		assertTrue d.hasErrors()
		assert d.errors.getFieldError('geneName').code == 'blank'
	}

	// test stat method not in list fails
	void testInvalidStatMethodFails() {

		mockDomain(Data)
		Data d = new Data (
				geneName:"Chrna3",
				statMethod:"ABC",
				POmIntensity:43.7435,
				POmFoldChangeP3:1.1465281309,
				POmFoldChangeP10:1.3002392637,
				VPIntensity:31.5705,
				VPFoldChangeP3:1.3032766718,
				VPFoldChangeP10:1.4011137492,
				probe:null,
				)
		assertFalse d.validate()
		assertTrue d.hasErrors()
		assert d.errors.getFieldError('statMethod').code == 'not.inList'
	}


	// test save invalid bean with FailOnError:true throws an exception
	void testSaveInvalidBeanThrowsError() {

		mockDomain(Data)
		Data d = new Data (
				geneName:"",
				statMethod:"ABC",
				POmIntensity:43.7435,
				POmFoldChangeP3:1.1465281309,
				POmFoldChangeP10:1.3002392637,
				VPIntensity:31.5705,
				VPFoldChangeP3:1.3032766718,
				VPFoldChangeP10:1.4011137492,
				probe:null,
				)
		try{
			d.save(failOnError:true)
			fails("should throw exception")
		}catch(ValidationException e){
		}
	}

	// test get

	void testGet() {

		mockDomain(Data)
		Data d = new Data (
				geneName:"Chrna3",
				statMethod:"MAS5",
				POmIntensity:43.7435,
				POmFoldChangeP3:1.1465281309,
				POmFoldChangeP10:1.3002392637,
				VPIntensity:31.5705,
				VPFoldChangeP3:1.3032766718,
				VPFoldChangeP10:1.4011137492,
				probe:null,
				)
		d.save(failOnError:true)
		def dataID = d.id
		Data d1 = Data.get(dataID)
		assertNotNull(d1)
		assert d1.statMethod == DataService.MAS5

		Data d2 = Data.findByGeneName("Chrna3")
		assertNotNull(d2)
		assert d2.VPIntensity == 31.5705

		Data d3 = Data.findByProbe(null)
		assertNotNull(d3)
		assert d3.VPFoldChangeP10 == 1.4011137492
	}

	// test get multiple results

	void testGetMultipleResults(){
		mockDomain(Data, buildGeneBase())
		Data d=Data.findByGeneName('Cav1')
		assertNotNull d
		assert d.POmIntensity == 43.7435*1.1

		d=Data.findByProbe('dummy')
		//d is not empty, but just the first element fulfilling the request
		assertNotNull d
	}

	// test update
	void testUpdate(){
		mockDomain(Data, buildGeneBase())
		assert Data.count() == 4
		Data d = Data.findByGeneName('Cav1')
		assertNotNull d
		d.probe='test'
		d.save()
		Data c = Data.findByGeneName('Cav1')
		assert c.probe == 'test'
	}

	// test delete

	void testDelete(){
		mockDomain(Data, buildGeneBase())
		assert Data.count() == 4
		Data d = Data.findByGeneName('Cav1')
		assertNotNull d
		d.delete()
		// 3 genes remaining
		assert Data.count() == 3
		d = Data.findByGeneName('Cav1')
		assertNull d
	}

	// test list

	void testList() {
		mockDomain(Data, buildGeneBase())
		assert Data.count() == 4
		Data.list().each{log.info("GeneName of bean with ID=${it.id} is ${it.geneName}")}
	}

	static def buildGeneBase(){
		return [
			['Chrna3', 1.0],
			['Cav1', 1.1],
			['Cckbr', 1.2],
			['Slc17a6', 1.3],
		].collect {
			new Data(
					geneName:it[0],
					statMethod:"MAS5",
					POmIntensity:43.7435*it[1],
					POmFoldChangeP3:1.1465281309*it[1],
					POmFoldChangeP10:1.3002392637*it[1],
					VPIntensity:31.5705*it[1],
					VPFoldChangeP3:1.3032766718*it[1],
					VPFoldChangeP10:1.4011137492*it[1],
					probe:"dummy",
					)
		}
	}
}
